package com.xyy.saas.payment.service.job.impl;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.xyy.saas.payment.adapter.channel.fm.config.BankConfigManager;
import com.xyy.saas.payment.constants.Constants;
import com.xyy.saas.payment.cores.api.PaymentLoanApi;
import com.xyy.saas.payment.cores.enums.BalanceAccountTypeEnum;
import com.xyy.saas.payment.cores.vo.XydAccountBalanceDto;
import com.xyy.saas.payment.dao.mapper.PayReportMapper;
import com.xyy.saas.payment.dao.mapper.PayResultOrderMapper;
import com.xyy.saas.payment.dao.mapper.RefundOrderMapper;
import com.xyy.saas.payment.manage.cores.bo.SyncFMPayReportConfigBO;
import com.xyy.saas.payment.manage.cores.enums.BusinessIdTypeEnum;
import com.xyy.saas.payment.manage.cores.vo.ResultVO;
import com.xyy.saas.payment.pojo.bo.BalanceMonitorAccountBo;
import com.xyy.saas.payment.pojo.bo.BalanceMonitorAccountConfigBo;
import com.xyy.saas.payment.pojo.vo.OpenAccountStatusSummaryVO;
import com.xyy.saas.payment.pojo.vo.OpenAccountStatusVO;
import com.xyy.saas.payment.service.OpenAccountService;
import com.xyy.saas.payment.service.PayAccountService;
import com.xyy.saas.payment.service.PlatformAccountsManage;
import com.xyy.saas.payment.service.job.BalanceMonitorService;
import com.xyy.saas.payment.trace.AlarmService;
import com.xyy.saas.payment.trace.DingTalkMessage;
import com.xyy.saas.payment.util.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.DependsOn;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.Charset;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyy.saas.payment.cores.constants.Constants.XYD_DISCOUNT_ACCOUNT;
import static com.xyy.saas.payment.cores.constants.Constants.XYD_REFUND_ACCOUNT;

@Service
@DependsOn({"apolloUtil"})
@Slf4j
public class BalanceMonitorServiceIpml implements BalanceMonitorService, InitializingBean {

    public static final String REFUND_CHARGE_USER_ID = "2713";
    public static final String WITHDRAWAL_CHARGE_USER_ID = "2714";
    public static final String BANLANCE_QIYE_WX_ALERT_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=47e660f4-1640-4244-898c-288c9a7dae67";

    public static final String OPEN_ACCOUNT_STATUS_QIYE_UPLOADFILE_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=a23f570a-456e-4f40-89cd-b28e7271bb85&type=file";
    public static final String OPEN_ACCOUNT_STATUS_QIYE_WX_ALERT_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a23f570a-456e-4f40-89cd-b28e7271bb85";
//    public static final String OPEN_ACCOUNT_STATUS_QIYE_UPLOADFILE_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/upload_media?key=790845cc-00ba-42ab-b773-d68c4c133cea&type=file";
//    public static final String OPEN_ACCOUNT_STATUS_QIYE_WX_ALERT_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=790845cc-00ba-42ab-b773-d68c4c133cea";

    @Value("${balance.alert.mobiles:18271421245}")
    private String balanceAlertMobiles;
    @Value("${balance.alert.threshold:300000}")
    private String balanceAlertThreshold;
    @Autowired
    private PayResultOrderMapper payResultOrderMapper;
    @Autowired
    private RefundOrderMapper refundOrderMapper;
    @Autowired
    private PlatformAccountsManage platformAccountsManage;
    @Autowired
    private OpenAccountService openAccountService;
    @Autowired
    private PayAccountService payAccountService;

    private BalanceMonitorAccountConfigBo balanceMonitorAccountConfig = JSONUtils.parse2Object(ApolloUtil.getProperty("balance_monitor_account"), BalanceMonitorAccountConfigBo.class);

    @Autowired
    private BankConfigManager bankConfigManager;
    // 账号类型和描述信息的映射关系
    private Map<String, String> accountTypeMap = new HashMap<>();

    @Autowired
    private PinganTradeCheckBillService pinganTradeCheckBillService;
    @Autowired
    private PayReportMapper payReportMapper;
    @Autowired
    private AlarmService alarmService;
    @Reference(version = "1.0.0")
    private PaymentLoanApi paymentLoanApi;

//    @Override
//    public List<BalanceMonitorVO> queryBalance() {
//        log.info("BalanceMonitorServiceIpml#queryBalance start.");
//        long time = System.currentTimeMillis();// 拉去 accountTypeMap 映射关系
//        accountTypeMap = bankConfigManager.getFuminAccountConfig().stream().collect(Collectors.toMap(SyncFMPayReportConfigBO::getAccountType,SyncFMPayReportConfigBO::getDesc));
//
//        List<BalanceMonitorVO> result = new ArrayList<>();
//        // startTime 上上周开始，endTime 上周结束
//        Date startTime = null;
//        Date endTime = null;
//        try {
//            startTime = DateUtil.getBeginDayOfLastLastWeek();
//            endTime = DateUtil.getEndDayOfLastWeek();
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//
//        // 计算前两周的支付金额，手续费，退款金额平均值
//        // 计算前两周的支付金额，手续费，退款金额平均值
//        List<BalanceMonitorAccountBo> balanceMonitorAccountList = balanceMonitorAccountConfig.getSpecialAccountList();
//        List<String> businessOrderTypes = balanceMonitorAccountList.stream().map(BalanceMonitorAccountBo::getBusinessOrderType).collect(Collectors.toList());
//        List<PayResultOrderAmountDTO> payResultOrders = payResultOrderMapper.countAmountByBusinessOrderType(businessOrderTypes, startTime, endTime);
//        for (BalanceMonitorAccountBo item : balanceMonitorAccountList) {
//            BalanceMonitorVO vo = new BalanceMonitorVO();
//            String businessOrderType = item.getBusinessOrderType();
//            String userId = item.getUserId();
//            vo.setBusinessOrderType(businessOrderType);
//            vo.setUserId(userId);
//            // 退款费
//            RefundOrder refundOrder = refundOrderMapper.countAmountByUserId(userId, startTime, endTime);
//            if (null != refundOrder) {
//                vo.setRefundAmount(refundOrder.getAmount() / 100 / 2);
//            }
//            // 支付费和手续费
//            for (PayResultOrderAmountDTO payResultOrder : payResultOrders) {
//                if (Objects.equals(payResultOrder.getBusinessOrderType(), businessOrderType)) {
//                    vo.setPayAmount(payResultOrder.getAmount() / 100 / 2);
//                    vo.setFee((payResultOrder.getAmount() / 100 / 2) * 0.0021);
//                    break;
//                }
//            }
//
//            vo.setBusinessOrderTypeName(accountTypeMap.getOrDefault(businessOrderType,"未知账户"));
//            result.add(vo);
//        }
//        log.info("BalanceMonitorServiceIpml#queryBalance start. cost:{}", System.currentTimeMillis() - time);
//        return result;
//    }

    @Override
    public void sendBalanceInfoToQiyeWx() {
        send();
    }

//    /**
//     * 监控余额是否enough，不足发出告警
//     */
//    @Override
//    public void monitorBalance() {
//        List<BalanceMonitorVO> balances = queryBalance();
//        if (!isBalanceEnough(balances)) {
//            log.info("BalanceMonitorServiceIpml#monitorBalance monitor balance. balance not enough. balances:{}", JSONUtils.toJSON(balances));
//            // 余额不足，引发告警通知
//            send(balances);
//        }
//    }

    @Override
    public void sendOpenAccountStatusToQiyeWx(){
        // 拿数据
        ResultVO<OpenAccountStatusSummaryVO> openAccountStatusSummaryVO = openAccountService.excelOpenAccount();
        OpenAccountStatusSummaryVO resultVO = openAccountStatusSummaryVO.getResult();

//        List<OpenAccountStatusVO> collect = resultVO.getOpenAccountStatusList().stream().filter(item -> OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_NO_TDATA.getCode().equals(item.getStatus())
//                || OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_FM_BASE_ACCOUNT_FAIL.getCode().equals(item.getStatus())
//                || OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_APPLY_PAY_USER_FAIL.getCode().equals(item.getStatus())).collect(Collectors.toList());

        // 计算数据
//        int sumFailCorporation = collect.size();
//        log.info("sendOpenAccountStatusToQiyeWx:collect:{}", JSONUtils.toJSON(collect));

//        int sumFailCorporationOver5 = countGMV(collect, 50000.0, null, false, false, null);
//        int sumFailCorporationOver5ForNoData = countGMV(collect, 50000.0, null, false, false, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_NO_TDATA);
//        int sumFailCorporationOver5ForFmBaseAccountFail = countGMV(collect, 50000.0, null, false, false, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_FM_BASE_ACCOUNT_FAIL);
//        int sumFailCorporationOver5ForApplyPayUserFail = countGMV(collect, 50000.0, null, false, false, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_APPLY_PAY_USER_FAIL);
//
//        int sumFailCorporationBetween0And5 = countGMV(collect, 0.0, 50000.0, false, true, null);
//        int sumFailCorporationBetween0And5ForNoData = countGMV(collect, 0.0, 50000.0, false, true, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_NO_TDATA);
//        int sumFailCorporationBetween0And5ForFmBaseAccountFail = countGMV(collect, 0.0, 50000.0, false, true, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_FM_BASE_ACCOUNT_FAIL);
//        int sumFailCorporationBetween0And5ForApplyPayUserFail = countGMV(collect, 0.0, 50000.0, false, true, OpenAccountReportStatusEnum.SUM_CORPORATION_FOR_APPLY_PAY_USER_FAIL);
//
//        int sumFailCorporationEqual0 = countGMV(collect, 0.0, 0.0, true, true, null);
        // 发送摘要
        StringBuilder sb = new StringBuilder();
        String title = DateUtil.format(DateUtil.now(), DateUtil.DATEFORMATDAY_2)+"平安换签日报：";
        sb.append("{\n\"msgtype\": \"markdown\",\n\"markdown\": {\n" +
                "\"content\": \""+title+"\\n" +
                "商户总数："+resultVO.getSumCorporation()+"\\n" +
                "未提交开户资料："+resultVO.getSumCorporationForNotData()+"，占比："+new BigDecimal(resultVO.getSumCorporationForNotData()*100).divide(new BigDecimal(resultVO.getSumCorporation()), 2, BigDecimal.ROUND_HALF_UP).doubleValue()+"%\\n" +
                "开富民基本户成功："+resultVO.getSumCorporationForFmBaseAccountSuccess()+"，占比："+new BigDecimal(resultVO.getSumCorporationForFmBaseAccountSuccess()*100).divide(new BigDecimal(resultVO.getSumCorporation()), 2, BigDecimal.ROUND_HALF_UP).doubleValue()+"%\\n" +
                "平安换签成功："+resultVO.getSumCorporationForPinganBaseAccountSuccess()+"，占比："+new BigDecimal(resultVO.getSumCorporationForPinganBaseAccountSuccess()*100).divide(new BigDecimal(resultVO.getSumCorporation()), 2, BigDecimal.ROUND_HALF_UP).doubleValue()+"%\\n");

        sb.append("\"}\n}");
        try {
            String content = new String(sb.toString().getBytes("utf-8"), "utf-8");
            log.info("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx content:{}", content);
            String result = HttpClientUtil.xyyHttpPostRequest(OPEN_ACCOUNT_STATUS_QIYE_WX_ALERT_URL, content, "application/json");
            log.info("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx httppost result:{}", result);
        } catch (Exception e) {
            log.error("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx send to qiyeWx error.");
        }

        List<OpenAccountStatusVO> vos = resultVO.getOpenAccountStatusList();
        String mediaId = "";
        try {
            // 创建临时文件
            File upload = new File(new File("").getAbsolutePath(), "Pingan_HuanQian_Report("+DateUtil.format(new Date(), DateUtil.DATEFORMATDAY_2)+").xlsx");
            upload.createNewFile();
            FileOutputStream fileOutputStream = new FileOutputStream(upload);
            // 向文件写数据
            ExportExcelUtil.createExcelDateFormatForOutStream(fileOutputStream, "平安换签报表", Constants.OPEN_ACCOUNT_STATUS_HEADER, Constants.OPEN_ACCOUNT_STATUS_FILED, vos, true, null);
            // 上传文件至企业微信
            String result = upload(OPEN_ACCOUNT_STATUS_QIYE_UPLOADFILE_URL, upload.getPath());
            log.info("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx upload result:{}", result);
            Map<String, String> stringStringMap = JSONUtils.parse2Map(result, String.class, String.class);
            mediaId = stringStringMap.get("media_id");
        } catch (Exception e) {
            log.error("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx send file to WX error.", e);
            return ;
        }

        // 发送文件至企业微信
        String str = "{\n" +
                "    \"msgtype\": \"file\",\n" +
                "    \"file\": {\n" +
                "         \"media_id\": \""+mediaId+"\"\n" +
                "    }\n" +
                "}";
        try {
            String content = new String(str.getBytes("utf-8"), "utf-8");
            log.info("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx content:{}", content);
            String result = HttpClientUtil.xyyHttpPostRequest(OPEN_ACCOUNT_STATUS_QIYE_WX_ALERT_URL, content, "application/json");
            log.info("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx httppost result:{}", result);
        } catch (Exception e) {
            log.error("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx send to qiyeWx error.");
        }
    }

//    private int countGMV(List<OpenAccountStatusVO> openAccountStatusList, Double min, Double max, boolean low, boolean high, OpenAccountReportStatusEnum status) {
//        int sum = 0;
//        if(min == null && max == null) {
//            // 无上下限
//            sum += openAccountStatusList.stream().filter(item -> status==null || (status.getCode().equals(item.getStatus()))).count();
//        } else if(max == null) {
//            // 无上限
//            sum += openAccountStatusList.stream().filter(item -> (status==null || (status.getCode().equals(item.getStatus())))
//                    && (item.getGmv() > min || (low && min == item.getGmv()))).count();
//        } else if(min == null) {
//            // 无下限
//            sum += openAccountStatusList.stream().filter(item -> (status==null || (status.getCode().equals(item.getStatus())))
//                    && (item.getGmv() < max || (high && max == item.getGmv()))).count();
//        } else {
//            // 有范围
//            sum += openAccountStatusList.stream().filter(item -> (status==null || (status.getCode().equals(item.getStatus())))
//                    && (item.getGmv() > min || (low && min == item.getGmv()))
//                    && (item.getGmv() < max || (high && max == item.getGmv()))).count();
//        }
//        return sum;
//    }

    public String upload(String url, String localFile) {
        CloseableHttpClient httpClient = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = HttpClients.createDefault();
            HttpPost httpPost = new HttpPost(url);
            httpPost.setConfig(RequestConfig.custom().setConnectTimeout(1000).build());
            // 把文件转换成流对象FileBody
            FileBody bin = new FileBody(new File(localFile));
            HttpEntity reqEntity = MultipartEntityBuilder.create()
                    // 相当于<input type="file" name="file"/>
                    .addPart("file", bin)
                    .build();
            httpPost.setEntity(reqEntity);

            // 发起请求 并返回请求的响应
            response = httpClient.execute(httpPost);
            // 获取响应对象
            HttpEntity resEntity = response.getEntity();
            if (resEntity != null) {
                return EntityUtils.toString(resEntity, Charset.forName("UTF-8"));
            }
            // 销毁
            EntityUtils.consume(resEntity);
        } catch (Exception e) {
            log.error("BalanceMonitorServiceIpml#sendOpenAccountStatusToQiyeWx#upload error.", e);
        } finally {
            try {
                if (response != null) {
                    response.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                if (httpClient != null) {
                    httpClient.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return "";
    }


    /**
     * 发送余额信息 -> 微信告警
     */
    private void send() {
        log.info("BalanceMonitorServiceIpml#send qiyewx alert start.");
        long time = System.currentTimeMillis();

        accountTypeMap = bankConfigManager.getFuminAccountConfig().stream().collect(Collectors.toMap(SyncFMPayReportConfigBO::getAccountType, SyncFMPayReportConfigBO::getDesc));
        log.info("BalanceMonitorServiceIpml#send accountTypeMap=" + accountTypeMap);

        StringBuilder sb = new StringBuilder();

        // 充值阀值
//        double refundChargeThreshold = countRefundChargeThreshold(balances);
//        double withdrawalChargeThreshold = countWithdrawalChargeThreshold(balances);

        // 药帮忙富民银行
        String refundCharge = platformAccountsManage.queryAccountBalance(REFUND_CHARGE_USER_ID);
        String withdrawalCharge = platformAccountsManage.queryAccountBalance(WITHDRAWAL_CHARGE_USER_ID);

        // 拼接告警数据
        sb.append("{\n\"msgtype\": \"markdown\",\n\"markdown\": {\n" +
                        "\"content\": \""+"药帮忙富民银行平台专用户日报"+"\\n");

        sb.append("> "+"退款专用户"+":"+refundCharge + "\\n");
        sb.append("> "+"手续费专用户"+":"+withdrawalCharge + "\\n");

        List<BalanceMonitorAccountBo> popAccountList = balanceMonitorAccountConfig.getPopAccountList();
        log.info("BalanceMonitorServiceIpml#send popAccountList=" + JSON.toJSONString(popAccountList));
        Map<String, String> popAccount = new LinkedHashMap<>();
        for (BalanceMonitorAccountBo balanceMonitorAccountBo : popAccountList) {
            String charge = platformAccountsManage.queryAccountBalance(balanceMonitorAccountBo.getUserId());
            log.info("BalanceMonitorServiceIpml#send balanceMonitorAccountBo charge=" + charge);
            String accountName = accountTypeMap.get(balanceMonitorAccountBo.getBusinessOrderType());
            log.info("BalanceMonitorServiceIpml#send accountName=" + accountName);
            if (accountName != null) {
                popAccount.put(accountName, charge);
            }
        }
        log.info("BalanceMonitorServiceIpml#send popAccount=" + popAccount);

        popAccount.forEach((key, value) -> {
            sb.append("> "+key+":"+value + "\\n");
        });

        // 药帮忙平安银行
        List<String> platformAccountBusinessIdList = new ArrayList<>();
        platformAccountBusinessIdList.add("ec_pingan_summary");
        platformAccountBusinessIdList.add("ec_pingan_refund");
        platformAccountBusinessIdList.add("ec_pingan_market");
        platformAccountBusinessIdList.add("ec_pingan_balance");
        platformAccountBusinessIdList.add("ec_pingan_in_brokerage");
        platformAccountBusinessIdList.add("ec_pingan_out_brokerage");
        platformAccountBusinessIdList.add("ec_pop_big_shop_pingan");

        Map<String, String> ybmPinganAccount = new LinkedHashMap<>();
        for (String businessId : platformAccountBusinessIdList) {
            String businessIdType = BusinessIdTypeEnum.EC_POP.getType();
            String payAccountID = payAccountService.getAccountIdByBusiness(businessIdType, businessId);

            String accountType = businessId.equals("ec_pingan_summary") || businessId.equals("ec_pingan_in_brokerage") ? BalanceAccountTypeEnum.FUNCTION_ACCOUNT.getType() : BalanceAccountTypeEnum.FUND_ACCOUNT.getType();
            String charge = platformAccountsManage.queryAccountBalance(payAccountID, accountType);

            ybmPinganAccount.put(pinganTradeCheckBillService.getAccountTypeByUserInfo(payAccountID, null, true), charge);
        }
        // 贴息子账户余额监控
        String balance = platformAccountsManage.queryAccountBalanceByNo("4294000000000072", "FUNCTION_ACCOUNT");
        ybmPinganAccount.put("平台贴息子账户", balance);

        sb.append("\\n");
        sb.append("药帮忙平安银行平台功能子账户日报"+"\\n");
        ybmPinganAccount.forEach((key, value) -> {
            sb.append("> "+key+":"+value + "\\n");
        });

        // 药帮忙自营店铺
        List<String> selfAccountBusinessIdList = new ArrayList<>();
        selfAccountBusinessIdList.add("ec_self_support_mini_XS530000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS140001");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS330000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS360000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS350000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS370000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS410000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS500000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS430000");
        selfAccountBusinessIdList.add("ec_self_support_mini_XS420000");

        Map<String, String> selfPinganAccount = new LinkedHashMap<>();
        for (String businessId : selfAccountBusinessIdList) {
            String businessIdType = BusinessIdTypeEnum.EC_SELF_SUPPORT.getType();
            String payAccountID = payAccountService.getAccountIdByBusiness(businessIdType, businessId);

            String accountType = BalanceAccountTypeEnum.FUND_ACCOUNT.getType();
            String charge = platformAccountsManage.queryAccountBalance(payAccountID, accountType);

            selfPinganAccount.put(pinganTradeCheckBillService.getAccountTypeByUserInfo(payAccountID, null, true), charge);
        }

        sb.append("\\n");
        sb.append("药帮忙自营店铺账户日报"+"\\n");
        selfPinganAccount.forEach((key, value) -> {
            sb.append("> "+key+":"+value + "\\n");
        });

        // 荷叶易宝支付
        List<BalanceMonitorAccountBo> hyAccountList = balanceMonitorAccountConfig.getHyAccountList();
        Map<String, String> hyAccount = new LinkedHashMap<>();
        for (BalanceMonitorAccountBo balanceMonitorAccountBo : hyAccountList) {
            String charge = platformAccountsManage.queryAccountBalance(balanceMonitorAccountBo.getUserId());
            log.info("BalanceMonitorServiceIpml#send balanceMonitorAccountBo charge=" + charge);
            String accountName = accountTypeMap.getOrDefault(balanceMonitorAccountBo.getBusinessOrderType(), balanceMonitorAccountBo.getAccountName());
            log.info("BalanceMonitorServiceIpml#send accountName=" + accountName);
            if (accountName != null) {
                hyAccount.put(accountName, charge);
            }
        }

        sb.append("\\n");
        sb.append("荷叶易宝支付平台子账户日报"+"\\n");
        hyAccount.forEach((key, value) -> {
            sb.append("> "+key+":"+value + "\\n");
        });

        // 小雨点专户日报
        addXydDailyAccountBalance(sb);

        sb.append("\"}\n}");

        // 发送企业微信
        try {
            String content = new String(sb.toString().getBytes("utf-8"), "utf-8");
            log.info("BalanceMonitorServiceIpml#send qiyewx alert content:{}", content);

            String response = HttpClientUtil.xyyHttpPostRequest(BANLANCE_QIYE_WX_ALERT_URL, content, "application/json");
            log.info("BalanceMonitorServiceIpml#send qiyewx alert response:{}", response);
        } catch (Exception e) {
            log.error("BalanceMonitorServiceIpml#sendBalanceToQiyeWx send to qiyeWx error.");
        }
        log.info("BalanceMonitorServiceIpml#send qiyewx alert end. cost:{}", System.currentTimeMillis() - time);

        try {
            if (ybmPinganAccount.containsKey("平安购物金子账户")) {
                String pinganBalance = ybmPinganAccount.getOrDefault("平安购物金子账户", "0");
                if (new BigDecimal(pinganBalance).compareTo(new BigDecimal(balanceAlertThreshold)) < 0) {
                    DingTalkMessage msg = DingTalkMessage.builder()
                            .type("平安银行平台功能子账户余额不足")
                            .method("BalanceMonitorServiceIpml.send")
                            .param("平安购物金子账户当前余额：" + pinganBalance)
                            .msg("平安购物金子账户余额不足，速充值！")
                            .build();
                    alarmService.alarm(msg, BANLANCE_QIYE_WX_ALERT_URL, balanceAlertMobiles);
                }
            }
        } catch (Exception e) {
            log.error("ybmPinganAccount alarm error", e);
        }
    }

    private void addXydDailyAccountBalance(StringBuilder sb) {
        sb.append("\\n");
        sb.append("小雨点专户日报" + "\\n");

        // 贴息专户
        com.xyy.saas.payment.cores.vo.ResultVO<XydAccountBalanceDto> discountResult = paymentLoanApi.queryXydAccountBalance(XYD_DISCOUNT_ACCOUNT);
        BigDecimal discountAvailableAmount = null;
        if (discountResult.isSuccess() && discountResult.getResult() != null) {
            discountAvailableAmount = discountResult.getResult().getAvailableAmount();
        } else {
            log.error("paymentLoanApi.queryXydAccountBalance failed discountResult:{}", JSON.toJSONString(discountResult));
        }

        sb.append("> " + "贴息专户余额" + ":" + discountAvailableAmount + "\\n");

        // 退款专户
        com.xyy.saas.payment.cores.vo.ResultVO<XydAccountBalanceDto> refundResult = paymentLoanApi.queryXydAccountBalance(XYD_REFUND_ACCOUNT);
        BigDecimal refundAvailableAmount = null;
        if (refundResult.isSuccess() && refundResult.getResult() != null) {
            refundAvailableAmount = refundResult.getResult().getAvailableAmount();
        } else {
            log.error("paymentLoanApi.queryXydAccountBalance failed refundResult:{}", JSON.toJSONString(refundResult));
        }

        sb.append("> " + "退款专户余额" + ":" + refundAvailableAmount + "\\n");
    }

//    /**
//     * 判断余额是否充足
//     * @param balances
//     * @return
//     */
//    private boolean isBalanceEnough(List<BalanceMonitorVO> balances) {
//        // 充值阀值
//        double refundChargeThreshold = countRefundChargeThreshold(balances);
//        double withdrawalChargeThreshold = countWithdrawalChargeThreshold(balances);
//        // 账户余额
//        double refundCharge = platformAccountsManage.queryAccountBalance(REFUND_CHARGE_USER_ID);
//        double withdrawalCharge = platformAccountsManage.queryAccountBalance(WITHDRAWAL_CHARGE_USER_ID);
//
//        return refundCharge>=refundChargeThreshold && withdrawalCharge>=withdrawalChargeThreshold;
//    }


//    /**
//     * 计算退款的阀值
//     * @return
//     */
//    private double countRefundChargeThreshold(List<BalanceMonitorVO> balances){
//        double refundChargeThreshold = balances.stream().mapToDouble(BalanceMonitorVO::getRefundAmount).sum();
//        return Math.ceil(refundChargeThreshold / 100) * 100;
//    }
//
//    /**
//     * 计算手续费的阀值
//     * @return
//     */
//    private double countWithdrawalChargeThreshold(List<BalanceMonitorVO> balances){
//        double withdrawalChargeThreshold = balances.stream().mapToDouble(BalanceMonitorVO::getFee).sum();
//        return Math.ceil(withdrawalChargeThreshold / 100) * 100;
//    }

    @Override
    public void afterPropertiesSet() throws Exception {
        BalanceMonitorAccountConfigBo tmpAccounts =  JSONUtils.parse2Object(ApolloUtil.getProperty("balance_monitor_account"), BalanceMonitorAccountConfigBo.class);
        if(tmpAccounts == null) {
            log.error("BalanceMonitorServiceIpml#onChange change balanceMonitorAccountConfig error.");
            return;
        }
        balanceMonitorAccountConfig = tmpAccounts;

        Set set = new HashSet();
        set.add("balance_monitor_account");
        //动态监听配置变化
        Config config = ConfigService.getAppConfig();
        config.addChangeListener(new ConfigChangeListener() {
            @Override
            public void onChange(ConfigChangeEvent changeEvent) {
                BalanceMonitorAccountConfigBo tmpAccounts =  JSONUtils.parse2Object(ApolloUtil.getProperty("balance_monitor_account"), BalanceMonitorAccountConfigBo.class);
                if(tmpAccounts == null) {
                    log.error("BalanceMonitorServiceIpml#onChange change balanceMonitorAccountConfig error.");
                    return;
                }
                balanceMonitorAccountConfig = tmpAccounts;
                log.info("BalanceMonitorServiceIpml#onChange change balanceMonitorAccountList success balanceMonitorAccountConfig:{} " , JSON.toJSONString(balanceMonitorAccountConfig));
            }
        }, set);
    }

}
